using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.IO;
using System.Xml;
using MacomberMap.Common.Database_Interface.CIM;
using MacomberMap.Common.Components;
using MacomberMap.Common.Internals;
using MacomberMap.Common.Database_Interface.CIM.Components;
using MacomberMap.Common.Database_Interface;
using System.Windows.Forms;
using MacomberMap.Common.Types;
using MacomberMap.Common.User_Interfaces.Components;
using MacomberMap.Common.Database_Interface.CIM.One_Line_Interface;
using MacomberMap.Common.Database_Interface.CIM.CIM_Interface;
using MacomberMap.Common.User_Interfaces.One_Lines;

namespace MacomberMap.Loader.Export
{
    /// <summary>
    /// This class handles exporting of the CRR map.
    /// </summary>
    public class MM_Exporter_CRR: MM_Exporter
    {
        #region Variable declarations

        /// <summary>
        /// Return the current progress
        /// </summary>
        public override float Progress
        {
            get { return Current / Total; }
        }
        /// <summary>
        /// The current step of export
        /// </summary>
        private float Current = 0;

        /// <summary>
        /// The total number of steps for export
        /// </summary>
        private float Total;

        /// <summary>
        /// The parameters for the CRR exporter - file name and Oracle Db instance for retrieving one-lines
        /// </summary>
        private KeyValuePair<String, MM_Database_Oracle> InParams;

        private MM_Database_Oracle OracleDb;

        private MM_Database_CIM CIMDb;
        #endregion

        #region Initialization
        /// <summary>
        /// Initialize the CRR exporter
        /// </summary>
        /// <param name="OutFileName">The outgoing file name</param>
        /// <param name="OracleDb">The connection to the MM Oracle Database instance</param>
        /// <param name="Parent">The list view in which this item will reside</param>
        /// <param name="CIMDb">CIM Database</param>
        public MM_Exporter_CRR(String OutFileName, MM_Database_Oracle OracleDb, MM_Database_CIM CIMDb, ListView Parent)
            : base(Parent, "CRR Exporter")
        {            
            this.InParams = new KeyValuePair<string, MM_Database_Oracle>(OutFileName, OracleDb);
            this.Total = (MM_Repository.Substations.Count * 2) + 1 + MM_Repository.Counties.Count + MM_Repository.Zones.Count + MM_Overall_Display.KVLevels.Count + MM_Repository.Lines.Count + MM_Repository.Companies.Count + MM_Database_CIM.ElementsOfType("etx:ConnectivityNodeGroup").Count;
            this.OracleDb = OracleDb;
            this.CIMDb = CIMDb;
        }      

        /// <summary>
        /// Export the CRRs
        /// </summary>
        public override void ProcessExporter()
        {
            InParams.Value.LoadZones();
            InParams.Value.LoadSubstations();
            InParams.Value.LoadLines();

            Current = 0;
            FileInfo NewInfo = new FileInfo(InParams.Key);
            Console.WriteLine("Writing file " + NewInfo.FullName);
            XmlTextWriter xW = new XmlTextWriter(InParams.Key, Encoding.UTF8);
            xW.Formatting = Formatting.Indented;           
            xW.WriteStartDocument(true);
            xW.WriteStartElement("CRR_Export");
            xW.WriteAttributeString("ExportedOn", XmlConvert.ToString(DateTime.Now, XmlDateTimeSerializationMode.Unspecified));
            
            //Now, export the zones
            xW.WriteStartElement("Zones"); 
            foreach (MM_Zone Zone in MM_Repository.Zones.Values)
            {
                Zone.WriteXML(xW);
                Current++;
            }
            xW.WriteEndElement();
            
            //Now, export the companies
            xW.WriteStartElement("Companies");
            foreach (MM_Company Company in MM_Repository.Companies.Values)                
            {
                Company.WriteXML(xW);                
                Current++;
            }
            xW.WriteEndElement();

            //Now, export the KV levels
            xW.WriteStartElement("KVLevels");
            foreach (MM_KVLevel KVLevel in MM_Overall_Display.KVLevels.Values)
            {
                KVLevel.WriteXML(xW);
                Current++;
            }
            xW.WriteEndElement();

            //Now, export the counties
            xW.WriteStartElement("Counties");
            MM_Repository.StateBoundary.WriteXML(xW);
            Current++;
            foreach (MM_Boundary Boundary in MM_Repository.Counties.Values)
            {
                Boundary.WriteXML(xW);
                Current++;
            }
            xW.WriteEndElement();



            //Now, export the substations
            xW.WriteStartElement("Substations");            
            foreach (MM_Substation Sub in MM_Repository.Substations.Values)
            {
                Sub.WriteXML(xW);
                Current++;
            }
            xW.WriteEndElement();

            //Now, export the lines.
            xW.WriteStartElement("Lines");
            foreach (MM_Line Line in MM_Repository.Lines.Values)
            {
                Line.WriteXML(xW);
                Current++;
            }
            xW.WriteEndElement();

            //Now, export the connectivity node group information
            xW.WriteStartElement("ConnectivityNodeGroups");
            foreach (CIM_Element ConnGroup in MM_Database_CIM.ElementsOfType("etx:ConnectivityNodeGroup"))
            {
                xW.WriteStartElement("NodeGroup");
                xW.WriteAttributeString("Name", ConnGroup.Name);
                xW.WriteAttributeString("TEID", ConnGroup.TEID);
                xW.WriteAttributeString("PSSE_Number", ConnGroup["etx:ConnectivityNodeGroup.PSSEBusNumber"]);
                xW.WriteAttributeString("PSSE_Name", ConnGroup["etx:ConnectivityNodeGroup.PSSEBusName"]);
                xW.WriteAttributeString("KVLevel", ConnGroup.VoltageLevel.Name);
                xW.WriteAttributeString("Substation", ConnGroup.Substation.TEID);
                xW.WriteEndElement();
                Current++;
            }
            xW.WriteEndElement();

           /* //Now, retrieve all of our substation one-lines, and export them as well.
            xW.WriteStartElement("StationOneLines");
            
            
            frmOneLineEditor olEditor = new frmOneLineEditor(OracleDb, CIMDb);
            Application.DoEvents();
            olEditor.Show();

            Dictionary<CIM_Element, CIM_TraceList> TraceList = new Dictionary<CIM_Element, CIM_TraceList>();
               

            foreach (MM_Substation Sub in MM_Repository.Substations.Values)
            {
                TraceList.Clear();
                CIM_Element SeedElement = MM_Database_CIM.TEIDs[Sub.TEID];
                 foreach (CIM_Element Elem in SeedElement.Elements)
                        if (MM_Database_CIM.ReverseTEIDs.ContainsKey(Elem))
                            TraceList.Add(Elem, null); 
                olEditor.CreateContingencyOneLine(SeedElement, TraceList);
                MM_OneLine_Viewer olView = olEditor.Controls["splMain"].Controls[0].Controls[0] as MM_OneLine_Viewer;
                olView.ExportDate = DateTime.Now;
                olView.WriteOneLineXml(xW, false);
                    


                /*if (!String.IsNullOrEmpty(OneLine = InParams.Value.LoadOneLine(Sub.TEID)))
                {
                    xW.WriteStartElement("OneLine");
                    xW.WriteAttributeString("TEID", Sub.TEID.ToString());
                    xW.WriteCData(OneLine);
                    xW.WriteEndElement();

                }* /
                Current++;
            }
            xW.WriteEndElement();*/
            xW.WriteEndDocument();
            xW.Flush();
            xW.Close();
            xW=null;
            EndTime = DateTime.Now;
        }

        #endregion
    }
}
